001 /* 002 * Copyright 2005 Stephen J. McConnell 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.library.info; 020 021 import java.util.Arrays; 022 import java.util.ArrayList; 023 import java.util.Properties; 024 025 import net.dpml.lang.Enum; 026 027 import net.dpml.transit.Artifact; 028 029 /** 030 * The ResourceDirective class describes an available resource. 031 * 032 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 033 * @version 1.1.0 034 */ 035 public class ResourceDirective extends AbstractDirective 036 { 037 /** 038 * External resource constant identifier. 039 */ 040 public static final Classifier EXTERNAL = Classifier.EXTERNAL; 041 042 /** 043 * Local resource constant identifier. 044 */ 045 public static final Classifier LOCAL = Classifier.LOCAL; 046 047 /** 048 * Anonymous resource constant identifier. 049 */ 050 public static final Classifier ANONYMOUS = Classifier.ANONYMOUS; 051 052 private final String m_scheme; 053 private final String m_name; 054 private final String m_version; 055 private final String m_basedir; 056 private final TypeDirective[] m_types; 057 private final DataDirective[] m_data; 058 private final DependencyDirective[] m_dependencies; 059 private final Classifier m_classifier; 060 private final FilterDirective[] m_filters; 061 private final InfoDirective m_info; 062 063 /** 064 * Creation of a new anonymous resource directive. 065 * @param scheme the schema name 066 * @param name the resource name 067 * @param version the resource version 068 * @param type the resource type 069 * @param properties suppliementary properties 070 * @return the resource directive 071 */ 072 public static ResourceDirective createAnonymousResource( 073 String scheme, String name, String version, String type, Properties properties ) 074 { 075 return new ResourceDirective( scheme, name, type, version, properties ); 076 } 077 078 /** 079 * Creation of a new resource directive. If the resource name if composite 080 * then the resource directive will be a module directive instance that either 081 * encloses the resource or enclosed a resource containing the resource. 082 * 083 * @param name the resource name 084 * @param version the resource version 085 * @param classifier LOCAL or EXTERNAL classifier 086 * @param basedir the project basedir 087 * @param info info descriptor 088 * @param data types produced by the resource 089 * @param dependencies resource dependencies 090 * @param properties suppliementary properties 091 * @param filters project filters 092 * @return the immediate enclosing resource 093 */ 094 public static ResourceDirective createResourceDirective( 095 String name, String version, Classifier classifier, String basedir, 096 InfoDirective info, DataDirective[] data, 097 DependencyDirective[] dependencies, Properties properties, 098 FilterDirective[] filters ) 099 { 100 int n = name.indexOf( "/" ); 101 if( n > -1 ) 102 { 103 ResourceDirective resource = null; 104 String[] elements = name.split( "/", -1 ); 105 for( int i = ( elements.length-1 ); i>-1; i-- ) 106 { 107 String elem = elements[i]; 108 if( i == ( elements.length-1 ) ) 109 { 110 resource = 111 new ResourceDirective( 112 elem, version, classifier, basedir, info, data, dependencies, 113 properties, filters ); 114 } 115 else 116 { 117 resource = 118 new ModuleDirective( 119 elem, null, Classifier.EXTERNAL, null, null, 120 new DataDirective[0], new DependencyDirective[0], 121 new ResourceDirective[]{resource}, null, null ); 122 } 123 } 124 return resource; 125 } 126 else 127 { 128 return new ResourceDirective( 129 name, version, classifier, basedir, info, data, 130 dependencies, properties, filters ); 131 } 132 } 133 134 /** 135 * Creation of a new annonomous resource directive. 136 * @param scheme the resource schema (artifact or link) 137 * @param name the resource name 138 * @param version the resource version 139 * @param properties suppliementary properties 140 */ 141 private ResourceDirective( 142 String scheme, String name, String type, String version, Properties properties ) 143 { 144 super( properties ); 145 146 if( null == name ) 147 { 148 throw new NullPointerException( "name" ); 149 } 150 151 m_name = name; 152 m_types = new TypeDirective[]{new TypeDirective( type )}; 153 m_data = m_types; 154 m_dependencies = new DependencyDirective[0]; 155 m_classifier = Classifier.ANONYMOUS; 156 m_version = version; 157 m_basedir = "."; 158 m_info = new InfoDirective( null, null ); 159 m_filters = new FilterDirective[0]; 160 m_scheme = scheme; 161 } 162 163 /** 164 * Creation of a new resource directive. 165 * @param name the resource name 166 * @param version the resource version 167 * @param classifier LOCAL or EXTERNAL classifier 168 * @param basedir the project basedir 169 * @param info info descriptor 170 * @param data type production data 171 * @param dependencies resource dependencies 172 * @param properties suppliementary properties 173 * @param filters suppliementary filters 174 */ 175 ResourceDirective( 176 String name, String version, Classifier classifier, String basedir, 177 InfoDirective info, DataDirective[] data, 178 DependencyDirective[] dependencies, Properties properties, 179 FilterDirective[] filters ) 180 { 181 super( properties ); 182 183 if( null == name ) 184 { 185 throw new NullPointerException( "name" ); 186 } 187 if( null == data ) 188 { 189 throw new NullPointerException( "data" ); 190 } 191 if( null == dependencies ) 192 { 193 throw new NullPointerException( "dependencies" ); 194 } 195 if( null == classifier ) 196 { 197 throw new NullPointerException( "classifier" ); 198 } 199 200 m_name = name; 201 m_version = version; 202 m_basedir = basedir; 203 m_classifier = classifier; 204 m_scheme = Artifact.ARTIFACT; 205 206 if( null == info ) 207 { 208 m_info = new InfoDirective( null, null ); 209 } 210 else 211 { 212 m_info = info; 213 } 214 215 m_dependencies = dependencies; 216 217 if( null == filters ) 218 { 219 m_filters = new FilterDirective[0]; 220 } 221 else 222 { 223 m_filters = filters; 224 } 225 226 ArrayList list = new ArrayList(); 227 for( int i=0; i<data.length; i++ ) 228 { 229 DataDirective directive = data[i]; 230 if( directive instanceof TypeDirective ) 231 { 232 list.add( directive ); 233 } 234 } 235 m_types = (TypeDirective[]) list.toArray( new TypeDirective[0] ); 236 m_data = data; 237 } 238 239 /** 240 * Return the resource name. 241 * @return the name 242 */ 243 public String getName() 244 { 245 return m_name; 246 } 247 248 /** 249 * Return the resource version. 250 * @return the version 251 */ 252 public String getVersion() 253 { 254 return m_version; 255 } 256 257 /** 258 * Return the resource basedir. 259 * @return the basedir 260 */ 261 public String getBasedir() 262 { 263 return m_basedir; 264 } 265 266 /** 267 * Return the info descriptor. 268 * @return the info descriptor 269 */ 270 public InfoDirective getInfoDirective() 271 { 272 return m_info; 273 } 274 275 /** 276 * Return the resource classifier. 277 * @return the classifier (LOCAL, EXTERNAL or ANONYMOUS) 278 */ 279 public Classifier getClassifier() 280 { 281 return m_classifier; 282 } 283 284 /** 285 * Return true if this represents a local project. 286 * @return true if local 287 */ 288 public boolean isLocal() 289 { 290 return LOCAL.equals( m_classifier ); 291 } 292 293 /** 294 * Return true if this represents a anonymous resource. 295 * @return true if anonymous 296 */ 297 public boolean isAnonymous() 298 { 299 return ANONYMOUS.equals( m_classifier ); 300 } 301 302 /** 303 * Return the scheme to use when declaring the published artifact (used 304 * in conjunction with anonymous resources. 305 * @return the scheme 306 */ 307 public String getScheme() 308 { 309 return m_scheme; 310 } 311 312 /** 313 * Return an array of types representing artifacts associated 314 * with the resource. 315 * @return the type directives 316 */ 317 public TypeDirective[] getTypeDirectives() 318 { 319 return m_types; 320 } 321 322 /** 323 * Return an array of supplimentary filter directives. 324 * @return the filter directives 325 */ 326 public FilterDirective[] getFilterDirectives() 327 { 328 return m_filters; 329 } 330 331 /** 332 * Return an array of supporting production data directives 333 * (including all produced types). 334 * @return the data directives 335 */ 336 public DataDirective[] getDataDirectives() 337 { 338 return m_data; 339 } 340 341 /** 342 * Return an named type. 343 * @param name the type name 344 * @return the type directives 345 * @exception TypeUnknownException if the type name if not recornized within 346 * the scope of the resource 347 */ 348 public TypeDirective getTypeDirective( String name ) throws TypeUnknownException 349 { 350 for( int i=0; i<m_types.length; i++ ) 351 { 352 TypeDirective type = m_types[i]; 353 if( name.equals( type.getID() ) ) 354 { 355 return type; 356 } 357 } 358 throw new TypeUnknownException( name ); 359 } 360 361 /** 362 * Return an array of dependency directives. 363 * @return the dependency directive array 364 */ 365 public DependencyDirective[] getDependencyDirectives() 366 { 367 return m_dependencies; 368 } 369 370 /** 371 * Return an dependency directive matching a supplied scope. 372 * @param scope the scope 373 * @return the dependency directive matching the supplied scope 374 */ 375 public DependencyDirective getDependencyDirective( Scope scope ) 376 { 377 for( int i=0; i<m_dependencies.length; i++ ) 378 { 379 DependencyDirective directive = m_dependencies[i]; 380 if( scope.equals( directive.getScope() ) ) 381 { 382 return directive; 383 } 384 } 385 return new DependencyDirective( scope, new IncludeDirective[0] ); 386 } 387 388 /** 389 * Compare this object with another for equality. 390 * @param other the other object 391 * @return true if equal 392 */ 393 public boolean equals( Object other ) 394 { 395 if( super.equals( other ) && ( other instanceof ResourceDirective ) ) 396 { 397 ResourceDirective object = (ResourceDirective) other; 398 if( !equals( m_name, object.m_name ) ) 399 { 400 return false; 401 } 402 else if( !equals( m_scheme, object.m_scheme ) ) 403 { 404 return false; 405 } 406 else if( !equals( m_version, object.m_version ) ) 407 { 408 return false; 409 } 410 else if( !equals( m_basedir, object.m_basedir ) ) 411 { 412 return false; 413 } 414 else if( !equals( m_info, object.m_info ) ) 415 { 416 return false; 417 } 418 else if( !Arrays.equals( m_data, object.m_data ) ) 419 { 420 return false; 421 } 422 else 423 { 424 return Arrays.equals( m_dependencies, object.m_dependencies ); 425 } 426 } 427 else 428 { 429 return false; 430 } 431 } 432 433 /** 434 * Compute the hash value. 435 * @return the hashcode value 436 */ 437 public int hashCode() 438 { 439 int hash = super.hashCode(); 440 hash ^= super.hashValue( m_name ); 441 hash ^= super.hashValue( m_scheme ); 442 hash ^= super.hashValue( m_version ); 443 hash ^= super.hashValue( m_basedir ); 444 hash ^= super.hashValue( m_info ); 445 hash ^= super.hashArray( m_data ); 446 hash ^= super.hashArray( m_dependencies ); 447 hash ^= super.hashArray( m_filters ); 448 return hash; 449 } 450 451 /** 452 * Resource classifier enumeration. 453 * @author <a href="mailto:dev-dpml@lists.ibiblio.org">The Digital Product Meta Library</a> 454 */ 455 public static final class Classifier extends Enum 456 { 457 static final long serialVersionUID = 1L; 458 459 /** 460 * Anonymous resources. 461 */ 462 public static final Classifier ANONYMOUS = new Classifier( "anonymous" ); 463 464 /** 465 * External resource. 466 */ 467 public static final Classifier EXTERNAL = new Classifier( "external" ); 468 469 /** 470 * Local resources. 471 */ 472 public static final Classifier LOCAL = new Classifier( "local" ); 473 474 /** 475 * Internal constructor. 476 * @param label the enumeration label. 477 */ 478 private Classifier( String label ) 479 { 480 super( label ); 481 } 482 483 /** 484 * Create a classified matching the supplied name. 485 * @param value the classifier name 486 * @return the classifier 487 * @exception IllegalArgumentException if the supplied value is not recognized 488 */ 489 public static Classifier parse( String value ) throws IllegalArgumentException 490 { 491 if( value.equalsIgnoreCase( "external" ) ) 492 { 493 return EXTERNAL; 494 } 495 else if( value.equalsIgnoreCase( "local" ) ) 496 { 497 return LOCAL; 498 } 499 else if( value.equalsIgnoreCase( "anonymous" ) ) 500 { 501 return ANONYMOUS; 502 } 503 else 504 { 505 final String error = 506 "Unrecognized module classifier argument [" + value + "]"; 507 throw new IllegalArgumentException( error ); 508 } 509 } 510 } 511 }